package Class;

import java.util.Arrays;
import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 姚东名
 * Date: 2024-05-10
 * Time: 15:06
 */
public class Test0510 {
    public static void main(String[] args) {
        //二维数组的定义：
        int[][] array = {{1, 2, 3}, {4, 5, 6}};
        int[][] array2 = new int[][]{{1, 2, 3}, {4, 5, 6}};
        int[][] array3 = new int[2][3];//两行三列
        //行数：
        System.out.println(array.length);//2
        //列数：
        System.out.println(array[0].length);//3

        //二维数组的打印：
        //二维数组 就是一个特殊的一维数组
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[0].length; j++) {
                System.out.print(array[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("=======");
        for (int[] tmpArray : array) {
            for (int x : tmpArray) {
                System.out.print(x + " ");
            }
            System.out.println();
        }
        System.out.println("=======");
        //调用库方法：deepT0String() -> toString的进阶版
        String ret = Arrays.deepToString(array);
        System.out.println(ret);//[[1, 2, 3], [4, 5, 6]]
    }

    public static String ToString(int[] array) {
        String ret = "[";
        for (int i = 0; i < array.length; i++) {
            ret += array[i];//字符串拼接
            if (i != array.length - 1) {
                ret += ", ";
            }
        }
        ret += "]";
        return ret;
    }

    public static void main12(String[] args) {
        //模拟实现ToString
        int[] array = {1, 2, 3, 4, 5};
        System.out.println(Arrays.toString(array));//[1, 2, 3, 4, 5]
        System.out.println(ToString(array));//[1, 2, 3, 4, 5]
    }

    public static void main11(String[] args) {
        //1.利用库方法判断数组的内容是否一样
        int[] array1 = {1, 2, 3, 4, 5};
        int[] array2 = {2, 3, 4, 5, 6};
        boolean flag = Arrays.equals(array1, array2);
        //如果数组的内容相同就返回true 否则返回false
        System.out.println(flag);//false
        //2.利用库方法对数组进行填充
        int[] ret = new int[10];
        //Arrays.fill(ret, 1);
        Arrays.fill(ret, 1, 3, -1);//[1, 3)
        System.out.println(Arrays.toString(ret));//[0, -1, -1, 0, 0, 0, 0, 0, 0, 0]
    }

    public static int[] copyArray(int[] array) {
        int[] copy = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            copy[i] = array[i];
        }
        return copy;
    }

    public static void main10(String[] args) {
        //利用库方法：
        int[] array = {1, 2, 31, 4, 15};//拷贝的数组   新的数组长度
        //利用库方法来对数组拷贝
        /*int[] copy = Arrays.copyOf(array,array.length*2);
        System.out.println(Arrays.toString(copy));//[1, 2, 31, 4, 15, 0, 0, 0, 0, 0] -> 相当于数组*/
        //利用库方法来对数组拷贝 ->可指定范围
        //int[] copy = Arrays.copyOfRange(array, 1, 3);//[1, 3)
        //System.out.println(Arrays.toString(copy));//[2, 31]
        //手动实现 数组拷贝
        int[] copy = copyArray(array);
        System.out.println(Arrays.toString(copy));
    }

    public static void bubbleSort(int[] array) {
        //i表示趟数 进行优化：
        for (int i = 0; i < array.length - 1; i++) {
            boolean flag = false;
            //j表示一趟要排序的次数 进行优化：假如不进行交换，就跳出循环
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tmp;
                    flag = true;
                }
            }
            if (flag == false) {
                return;
            }
        }
    }

    public static void main8(String[] args) {
        //冒泡排序：从小到大排序
        int[] array = {8, 10, 6, 9, 3};
        System.out.println("排序前的数组：" + Arrays.toString(array));
        //bubbleSort(array);
        Arrays.sort(array);//利用库方法来进行排序
        System.out.println("排序后的数组：" + Arrays.toString(array));
    }

    public static int findNum(int[] array, int key) {
        for (int i = 0; i < array.length; i++) {
            if (key == array[i]) {
                return i;
            }
        }
        return -1;
    }

    //二分查找 -> 数组必须是有序的
    /*public static int binarySearch(int[] array, int key) {
        int left = 0;
        int right = array.length - 1;
        while(left <= right) {
            int mid = (left + right) / 2;
            if(array[mid] == key) {
                return mid;
            }else if(array[mid] < key) {
                left = mid + 1;
            }else {
                right = mid - 1;
            }
        }
        return -1;
    }*/
    public static int binarySearch(int[] array, int key) {
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (key == array[mid]) {
                return mid;
            } else if (key > array[mid]) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }

    public static void main7(String[] args) {
        //顺序查找 与 二分查找
        //1.顺序查找
        int[] array = {1, 2, 3, 4, 5};
        Scanner scanner = new Scanner(System.in);
        int key = scanner.nextInt();
        //int ret = findNum(array, key);
        int ret = binarySearch(array, key);
        if (ret < 0) {
            System.out.println("不存在");
        } else {
            System.out.println("下标是：" + ret);
        }

    }

    public static void main6(String[] args) {
        int[] array = null;
        System.out.println(array);
        System.out.println(array.length);//出现报错，为空指针异常
        //如果将来代码 报错 空指针异常，那么我们要做的是找出这行代码中的引用。
        //总结：
        /*
        1.int[] array = null; 代表这个引用不能指向任何对象
        2.array1 = array2; 代表array1这个引用 指向了 array2这个引用指向的对象
        3.一个引用不可能同时指向2个对象
         */
    }

    public static void funcc1(int[] array) {
        array[0] = 15;
    }

    public static void funcc2(int[] array) {
        //本来array指向的对象是{ 1, 2, 3, 4, 5 }
        array = new int[]{5, 4, 3, 2, 1};
        //变成了指向的对象是{ 5, 4, 3, 2, 1 } 结论：引用变量只能指向一个对象！！，不可能指向多个对象
        //原因：因为是局部变量，出了方法，就自动被JVM回收了，所以地址都不一样
    }

    public static void main5(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        //funcc1(array);
        //System.out.println(Arrays.toString(array));//[15, 2, 3, 4, 5]
        funcc2(array);
        System.out.println(Arrays.toString(array));/*[1, 2, 3, 4, 5]*/
    }

    public static void func2(int[] array1) {
        for (int i = 0; i < array1.length; i++) {
            array1[i] = array1[i] * 2;//直接对array1数组的值进行修改因为array1与array存储的地址一样，所以array数组的数据也改了
        }
    }

    public static void main4(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        System.out.println(Arrays.toString(array));//[1, 2, 3, 4, 5]
        func2(array);
        System.out.println(Arrays.toString(array));//[2, 4, 6, 8, 10]
    }

    public static int[] func1(int[] array) {
        //方法1：让数组中数据的大小增加2倍
        int[] ret = new int[array.length];//申请的空间的大小与形参的大小的大小一样
        for (int i = 0; i < array.length; i++) {
            ret[i] = array[i] * 2;
        }
        return ret;//把临时变量(ret数组)的地址返回去了
    }//程序跑到这里，形参会自动被JVM回收，但是空间还没有回收

    public static void main3(String[] args) {
        int[] array = {1, 2, 3, 4, 5};
        int[] tmp = func1(array);
        System.out.println(Arrays.toString(array));//[1, 2, 3, 4, 5]
        //用tmp来接收局部变量的地址，所以可以用tmp接收到的地址来访问ret数组所创造的数组空间 -> 里面的内容也可以修改
        System.out.println(Arrays.toString(tmp));//[2, 4, 6, 8, 10]
    }

    public static void main2(String[] args) {
        int[] array1 = new int[3];
        array1[0] = 10;
        array1[1] = 20;
        array1[2] = 30;
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + " ");//10 20 30
        }

        int[] array2 = new int[]{1, 2, 3, 4, 5};
        array2[0] = 40;
        array2[1] = 50;
        array2[2] = 60;
        //把array2的地址赋值给 array1，让array1也可以访问array2中的数据
        array1 = array2;
        array1[3] = 100;
        array1[4] = 200;//把array2中下标3、4的值给改了
        System.out.println();
        for (int i = 0; i < array2.length; i++) {
            System.out.print(array2[i] + " ");//40 50 60 100 200
        }
        //array1 = array2：
        //1.array1 这个引用 指向array2这个引用所指向的对象
        //2.当2个引用 同时指向一个对象时，通过任何一个引用 都可以修改这个对象的值
    }

    public static void main1(String[] args) {
        //基本数据类型的变量和引用类型的变量(简称引用)
        //int short        String array
        //JVM(Java虚拟机): 堆 + 本地方法栈 + Java虚拟机栈 + 方法区 + 程序计数器
        //一共两个栈：
        //1.本地方法栈：会执行一些底层是由C/C++ 代码 实现的方法。
        //2.Java虚拟机栈：就是平时说的栈
        int[] array = {1, 2, 3, 4, 5};
        //System.out.println(array);//[I@1b6d3586
        //[ 代表的是数组 、I代表数据类型是 int型 @作为分割线 b6d3586 作为一个数组的地址

        //引用 指向 对象：引用在栈区 而 对象在堆区上 引用可以看成存储的是对象的地址
        System.out.println(array[0]);//1
        //通过array这个引用 访问当前的这个对象的 0下标
        System.out.println(array.length);//5 数组长度为 5
        //通过array这个引用 访问当前的这个对象的长度
    }
}
